package contatos.collection;

import contatos.model.Contato;
import contatos.view.ProgressBarView;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 *
 * @author felipe
 */
public class XML {

    private ProgressBarView view;

    public XML() {

    }

    public String selecionarXML() {

        String caminhoArquivo = null;

        final JFileChooser fc = new JFileChooser();
        FileNameExtensionFilter xmlfilter = new FileNameExtensionFilter("xml files (*.xml)", "xml");
        fc.setFileFilter(xmlfilter);
        int returnVal = fc.showOpenDialog(null);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            caminhoArquivo = fc.getSelectedFile().getAbsolutePath();
        }
        return caminhoArquivo;
    }

    /**
     * Esse método permite a importação de um arquivo de contatos em XML no
     * seguinte padrão:
     * <pre>
     * {@code
     * <contatos>
     *   <contato>
     *       <Id>1</Id>
     *       <Nome>Madeline Mullins</Nome>
     *       <Telefone>(22) 9689-2958</Telefone>
     *   </contato>
     * </contatos>
     * }
     * </pre>
     *
     * @param colecao Colecao de contatos que recebera os dados do XML
     * @throws javax.xml.parsers.ParserConfigurationException
     * @throws org.xml.sax.SAXException
     * @throws java.io.IOException
     *
     */
    public void importarXML(Collection colecao) throws ParserConfigurationException, SAXException, IOException {

        //configurando a barra de progresso
        view = new ProgressBarView();
        view.getBtnFechar().setEnabled(false);
        view.getProgressBar().setStringPainted(true);

        view.getBtnFechar().addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                view.setVisible(false);
                view.dispose();
            }
        });

        String caminhoArquivo = selecionarXML();

        if (caminhoArquivo != null) {

            //mostrando a view de progresso
            view.setVisible(true);

            //construtor de documento
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();

            //realizar o parse do xml
            org.w3c.dom.Document document = builder.parse(new File(caminhoArquivo));

            //normaliza o xml
            document.getDocumentElement().normalize();

            //percorrendo os nós
            NodeList nList = document.getElementsByTagName("contato");
            for (int i = 0; i < nList.getLength(); i++) {
                Node node = nList.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element eElement = (Element) node;
                    String nome = eElement.getElementsByTagName("Nome").item(0).getTextContent();
                    String telefone = eElement.getElementsByTagName("Telefone").item(0).getTextContent().replace(" ", "");
                    String operadora = eElement.getElementsByTagName("Operadora").item(0).getTextContent();
                    String uf = eElement.getElementsByTagName("UF").item(0).getTextContent();
                    
                    boolean add = colecao.add(new Contato(nome, telefone.trim(), operadora, uf));

                    int porcentagem = i * 100 / nList.getLength();
                    view.getProgressBar().setValue(porcentagem);
                    if (add) {
                        view.getTxtAreaProgress().append("Contato " + nome + " importado com sucesso!\n");
                    } else {
                        view.getTxtAreaProgress().append("Contato " + nome + " não importado, número já existente: " + telefone + "\n");
                    }
                }
            }

            view.getProgressBar().setValue(100);
            view.getBtnFechar().setEnabled(true);

            try {
                Contatos contato = Contatos.getInstancia();
                contato.Persistir(true);
            } catch (Exception ex) {
                Logger.getLogger(XML.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    }

    public void exportarXML(TreeSet<Contato> contatos) throws TransformerException {
        try {
            String caminhoArquivo = selecionarXML();

            if (caminhoArquivo != null) {
                DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

                //elemento raiz
                Document doc = docBuilder.newDocument();
                Element rootElement = doc.createElement("contatos");
                doc.appendChild(rootElement);

                //percorrendo o treeset de contatos
                for (Contato contato : contatos) {
                    Element cont = doc.createElement("contato");
                    rootElement.appendChild(cont);

                    Element nome = doc.createElement("Nome");
                    nome.appendChild(doc.createTextNode(contato.getNome()));
                    cont.appendChild(nome);

                    Element telefone = doc.createElement("Telefone");
                    telefone.appendChild(doc.createTextNode(contato.getTelefone()));
                    cont.appendChild(telefone);

                    Element operadora = doc.createElement("Operadora");
                    operadora.appendChild(doc.createTextNode(contato.getOperadora()));
                    cont.appendChild(operadora);

                    Element uf = doc.createElement("UF");
                    uf.appendChild(doc.createTextNode(contato.getUf()));
                    cont.appendChild(uf);

                }

                //escrevendo a estrutura no arquivo
                TransformerFactory transformerFactory = TransformerFactory.newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                DOMSource source = new DOMSource(doc);
                StreamResult result = new StreamResult(new File(caminhoArquivo));

                //transformando o arquivo para indentar
                transformer.transform(source, result);

                JOptionPane.showMessageDialog(null, "Arquivo exportado com sucesso");
            }

        } catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (TransformerException tfe) {
            tfe.printStackTrace();
        }
    }
}
